package com.company;

/**
 * The class DivisionInAColumn makes calculations and writes a process of division in a column.
 * @author Dusheyko Dima
 * @version 1.05 05.10.2013
 */
public class DivisionInAColumn {
    private final int ROUND_NUMBER_TO = 2;
    private int divisorSize;
    private int markOfFraction;
    private String isNegativeValue;
    private String result;

    public DivisionInAColumn(int divisorArg, int dividendArg, float markIsNegativeValue) {
        result           = "";
        markOfFraction   = 0;
        int divisor      = divisorArg < 0 ? divisorArg * (-1) : divisorArg;
        StringBuilder dividendAsString = new StringBuilder(String.valueOf(dividendArg));
        dividendAsString = dividendArg < 0 ? dividendAsString.delete(0, 1) : dividendAsString;
        divisorSize      = getNumberOfDigit(divisor);
        isNegativeValue  = markIsNegativeValue < 0 ? "-" : "";
        getPartForDividend(divisor, dividendAsString, 0, 0);
    }

    /**
     * It's a recursion method. It gets a part of a string, how it makes people and calls the next method.
     * It creates a part of a result after a point, if it is necessary.
     * @param countOfSpaces           - default value is 0
     * @param restFromPreviousDivide  - default value is 0
     */
    protected void getPartForDividend(int divisor, StringBuilder dividendAsString, int countOfSpaces, int restFromPreviousDivide) {
        int partOfDividendInt = 0;

        partOfDividendInt = dividendAsString.length() >= divisorSize ? Integer.parseInt(dividendAsString.substring(0, divisorSize))
                                                                     : Integer.parseInt(dividendAsString.toString());

        if (partOfDividendInt < divisor && partOfDividendInt != 0) {

            if (dividendAsString.length() > divisorSize) {
                partOfDividendInt = Integer.parseInt(dividendAsString.substring(0, divisorSize + 1));
            }

            if (dividendAsString.length() <= divisorSize && markOfFraction == 0) {

                if(restFromPreviousDivide == 0 && partOfDividendInt < divisor) {
                    result += "0";
                }

                result += ".";
                while (partOfDividendInt < divisor) {
                    partOfDividendInt *= 10;
                    markOfFraction    += 1;
                    if (markOfFraction > 1) {
                        result += "0";
                    }
                }
            }

            if (dividendAsString.length() <= divisorSize && markOfFraction != 0) {
                markOfFraction    += 1;
                partOfDividendInt *= 10;
            }
        }
        makeDividend(divisor, dividendAsString, partOfDividendInt, countOfSpaces);
    }

    /**
     * The method shows one iteration from a division cycle, and cleans a class string after iteration.
     */
    protected void makeDividend(int divisor, StringBuilder dividendAsString, int partOfDividendInt, int countOfSpaces) {
        int rest     = 0;
        int quotient = 0;

        if (partOfDividendInt != 0) {
            quotient = partOfDividendInt / divisor;
            result   += quotient;
            rest     = divisor * quotient;
            printValue(partOfDividendInt, countOfSpaces);
            printValue(rest, countOfSpaces);

            rest = partOfDividendInt - rest;
            dividendAsString.delete(0, getNumberOfDigit(partOfDividendInt));

            if (rest != 0) {
                dividendAsString.insert(0, rest) ;
            }
        }
        else {
            result += dividendAsString.substring(0, divisorSize);
            dividendAsString.delete(0, divisorSize);
        }

        if (dividendAsString.length() != 0 && markOfFraction < ROUND_NUMBER_TO) {
            if(rest == 0) {
                countOfSpaces += getNumberOfDigit(partOfDividendInt);
            }
            getPartForDividend(divisor, dividendAsString, countOfSpaces, rest);
        }
        else {
            printValue(partOfDividendInt - (divisor * quotient), countOfSpaces);
        }
    }

    private void printValue(int value, int countOfSpaces) {
        for (int i = 0; i < countOfSpaces; ++i) {
            System.out.print(" ");
        }
        System.out.println(value);
    }

    private int getNumberOfDigit(int currentInt) {
        return currentInt == 0 ? 1 : (int) Math.log10(currentInt) + 1;
    }

    public String getResult() {
        if (isNegativeValue == "-")
            result = isNegativeValue + result;
        return result;
    }
}
